﻿using AutoMapper;
using DTcms.Core.API.Filters;
using DTcms.Core.Common.Emums;
using DTcms.Core.Common.Extensions;
using DTcms.Core.Common.Helpers;
using DTcms.Core.IServices;
using DTcms.Core.Model.Models;
using DTcms.Core.Model.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.JsonPatch;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace DTcms.Core.API.Controllers
{
    /// <summary>
    /// 广告内容
    /// </summary>
    [Route("admin/advert/banner")]
    [ApiController]
    public class AdvertBannersController(IAdvertBannerService advertBannersService, IUserService userService, IMapper mapper) : ControllerBase
    {
        private readonly IAdvertBannerService _advertBannersService = advertBannersService;
        private readonly IUserService _userService = userService;
        private readonly IMapper _mapper = mapper;

        #region 管理员调用接口==========================
        /// <summary>
        /// 根据ID获取数据
        /// 示例：/admin/advert/banner/1
        /// </summary>
        [HttpGet("{id}")]
        [Authorize(Roles = "SuperAdmin,Admin")]
        [AuthorizeFilter("AdvertBanner", ActionType.View)]
        public async Task<IActionResult> GetById([FromRoute] int id, [FromQuery] BaseParameter param)
        {
            //检测参数是否合法
            if (!param.Fields.IsPropertyExists<AdvertBannersDto>())
            {
                throw new ResponseException("请输入正确的属性参数");
            }
            //查询数据库获取实体
            var model = await _advertBannersService.QueryAsync<AdvertBanners>(x => x.Id == id,
                query => query.Include(a => a.Advert),
                WriteRoRead.Write)
                ?? throw new ResponseException($"数据[{id}]不存在或已删除");

            //使用AutoMapper转换成ViewModel
            //根据字段进行塑形
            var result = _mapper.Map<AdvertBannersDto>(model).ShapeData(param.Fields);
            return Ok(result);
        }

        /// <summary>
        /// 获取数据列表
        /// 示例：/admin/advert/banner?pageSize=10&pageIndex=1
        /// </summary>
        [HttpGet]
        [Authorize(Roles = "SuperAdmin,Admin")]
        [AuthorizeFilter("AdvertBanner", ActionType.View)]
        public async Task<IActionResult> GetList([FromQuery] BaseParameter searchParam, [FromQuery] PageParamater pageParam, [FromQuery] int parentId = 0)
        {
            //检测参数是否合法
            if (searchParam.OrderBy != null && !searchParam.OrderBy.TrimStart('-').IsPropertyExists<AdvertBannersDto>())
            {
                throw new ResponseException("请输入正确的排序参数");
            }
            if (!searchParam.Fields.IsPropertyExists<AdvertBannersDto>())
            {
                throw new ResponseException("请输入正确的属性参数");
            }

            //获取数据列表
            var list = await _advertBannersService.QueryPageAsync<AdvertBanners>(
                pageParam.PageSize,
                pageParam.PageIndex,
                x => (parentId == 0 || parentId == x.AdvertId)
                && (string.IsNullOrWhiteSpace(searchParam.Keyword) || (x.Title != null && x.Title.Contains(searchParam.Keyword))),
                query => query.Include(a => a.Advert),
                searchParam.OrderBy ?? "SortId,-Id");

            //x-pagination
            var paginationMetadata = new
            {
                totalCount = list.TotalCount,
                pageSize = list.PageSize,
                pageIndex = list.PageIndex,
                totalPages = list.TotalPages
            };
            Response.Headers.Append("x-pagination", JsonHelper.ToJson(paginationMetadata));

            //映射成DTO
            var resultDto = _mapper.Map<IEnumerable<AdvertBannersDto>>(list.Items).ShapeData(searchParam.Fields);
            return Ok(resultDto);
        }

        /// <summary>
        /// 添加一条记录
        /// 示例：/admin/advert/banner
        /// </summary>
        [HttpPost]
        [Authorize(Roles = "SuperAdmin,Admin")]
        [AuthorizeFilter("AdvertBanner", ActionType.Add)]
        public async Task<IActionResult> Add([FromBody] AdvertBannersEditDto modelDto)
        {
            //映射成实体
            var model = _mapper.Map<AdvertBanners>(modelDto);
            //获取当前用户名
            model.AddBy = _userService.GetUserName();
            model.AddTime = DateTime.Now;
            //写入数据库
            await _advertBannersService.AddAsync<AdvertBanners>(model);
            //映射成DTO再返回，否则出错
            var result = _mapper.Map<AdvertBannersDto>(model);
            //由于没有调用方法，手动清空缓存
            await _advertBannersService.RemoveCacheAsync<Adverts>(true);

            return Ok(result);
        }

        /// <summary>
        /// 修改一条记录
        /// 示例：/admin/advert/banner/1
        /// </summary>
        [HttpPut("{id}")]
        [Authorize(Roles = "SuperAdmin,Admin")]
        [AuthorizeFilter("AdvertBanner", ActionType.Edit)]
        public async Task<IActionResult> Update([FromRoute] int id, [FromBody] AdvertBannersEditDto modelDto)
        {
            //查找记录
            var model = await _advertBannersService.QueryAsync<AdvertBanners>(x => x.Id == id, null, WriteRoRead.Write)
                ?? throw new ResponseException($"记录[{id}]不存在或已删除");

            //更新操作AutoMapper替我们完成，只需要调用保存即可
            _mapper.Map(modelDto, model);
            var result = await _advertBannersService.SaveAsync();

            //由于没有调用方法，手动清空缓存
            if (result)
            {
                await _advertBannersService.RemoveCacheAsync<Adverts>(true);
            }

            return NoContent();
        }

        /// <summary>
        /// 局部更新一条记录
        /// 示例：/admin/advert/banner/1
        /// Body：[{"op":"replace","path":"/title","value":"new title"}]
        /// </summary>
        [HttpPatch("{id}")]
        [Authorize(Roles = "SuperAdmin,Admin")]
        [AuthorizeFilter("AdvertBanner", ActionType.Edit)]
        public async Task<IActionResult> Update([FromRoute] long id, [FromBody] JsonPatchDocument<AdvertBannersEditDto> patchDocument)
        {
            var model = await _advertBannersService.QueryAsync<AdvertBanners>(x => x.Id == id, null, WriteRoRead.Write)
                ?? throw new ResponseException($"数据[{id}]不存在或已删除");

            var modelToPatch = _mapper.Map<AdvertBannersEditDto>(model);
            patchDocument.ApplyTo(modelToPatch, ModelState);
            //验证数据是否合法
            if (!TryValidateModel(modelToPatch))
            {
                return ValidationProblem(ModelState);
            }
            //更新操作AutoMapper替我们完成，只需要调用保存即可
            _mapper.Map(modelToPatch, model);
            var result = await _advertBannersService.SaveAsync();

            //由于没有调用方法，手动清空缓存
            if (result)
            {
                await _advertBannersService.RemoveCacheAsync<AdvertBanners>(true);
            }

            return NoContent();
        }

        /// <summary>
        /// 删除一条记录
        /// 示例：/admin/advert/banner/1
        /// </summary>
        [HttpDelete("{id}")]
        [Authorize(Roles = "SuperAdmin,Admin")]
        [AuthorizeFilter("AdvertBanner", ActionType.Delete)]
        public async Task<IActionResult> Delete([FromRoute] int id)
        {
            if (!await _advertBannersService.ExistsAsync<AdvertBanners>(x => x.Id == id, WriteRoRead.Write))
            {
                throw new ResponseException($"记录[{id}]不存在或已删除");
            }
            var result = await _advertBannersService.DeleteAsync<AdvertBanners>(x => x.Id == id);

            return NoContent();
        }

        /// <summary>
        /// 批量删除记录(级联数据)
        /// 示例：/admin/advert/banner?ids=1,2,3
        /// </summary>
        [HttpDelete]
        [Authorize(Roles = "SuperAdmin,Admin")]
        [AuthorizeFilter("AdvertBanner", ActionType.Delete)]
        public async Task<IActionResult> DeleteByIds([FromQuery] string Ids)
        {
            if (Ids == null)
            {
                throw new ResponseException("传输参数不可为空");
            }
            //将ID列表转换成IEnumerable
            var ids = Ids.ToIEnumerable<int>();
            if (ids == null)
            {
                throw new ResponseException("传输参数不符合规范");
            }
            //执行批量删除操作
            await _advertBannersService.DeleteAsync<AdvertBanners>(x => ids.Contains(x.Id));

            return NoContent();
        }
        #endregion
    }
}
